package com.coderly.onlinegallerysharingplatform.common.auth;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import cn.dev33.satoken.util.SaResult;
import com.coderly.onlinegallerysharingplatform.toolkit.StpKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.PostConstruct;

@Configuration
@Slf4j
public class SaTokenConfig implements WebMvcConfigurer {

    @PostConstruct
    public void setSaTokenConfig() {
        // 设定 StpUtil 使用的 SaTokenConfig 配置参数对象
        cn.dev33.satoken.config.SaTokenConfig config1 = new cn.dev33.satoken.config.SaTokenConfig();
        config1.setTokenName("Authorization");
        config1.setTimeout(-1);
        config1.setTokenStyle("random-64");
        config1.setTokenPrefix("Bearer");
        config1.setIsReadCookie(false);
        StpKit.SPACE.setConfig(config1);
        //log.info("SPACE-token配置成功");

//        cn.dev33.satoken.config.SaTokenConfig config2 = new cn.dev33.satoken.config.SaTokenConfig();
//        config2.setTokenName("Authorization");
//        config2.setTimeout(-1);
//        config2.setActiveTimeout(-1);
//        config2.setIsConcurrent(true);
//        config2.setIsShare(true);
//        config2.setTokenStyle("random-128");
//        config2.setIsLog(true);
//        config2.setTokenPrefix("Bearer");
//        config2.setIsReadCookie(false);
//        StpKit.DEFAULT.setConfig(config2);
        //log.info("DEFAULT-TOKEN配置成功");
    }

    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()

                // 指定 [拦截路由] 与 [放行路由]
                .addInclude("/**").addExclude("/favicon.ico")

                // 认证函数: 每次请求执行
                .setAuth(obj -> {
                    // log.info("请求接口" + SaHolder.getRequest().getRequestPath() + SaHolder.getRequest().getHeader("Authorization-Login"));
                    SaManager.getLog().debug("----- 请求path={}  提交login-token={}", SaHolder.getRequest().getRequestPath(), StpUtil.getTokenValue());
                    SaManager.getLog().debug("----- 请求path={}  提交space-token={}", SaHolder.getRequest().getRequestPath(), StpKit.SPACE.getTokenValue());
                    // 系统级登录认证
                    SaRouter.match("/**")
                            .notMatch(
                                    "/user/login",
                                    "/user/verification/code/send",
                                    "/user/getDataInfo/count",
                                    "/picture/list/page",
                                    "/picture/tag_category",
                                    "/picture_detail/**",
                                    "/picture/get",
                                    "/picture/list/page/vo/cache",
                                    "/picture/list/my_public_approved/page",
                                    "/doc.html",                 // Knife4j 接口文档页面
                                    "/v2/api-docs",              // Knife4j API 文档
                                    "/swagger-ui.html",          // Swagger UI 页面
                                    "/swagger-resources/**",     // Swagger 资源路径
                                    "/webjars/**"
//                                    "/space_user/**"
                            )
                            .notMatch(SaHttpMethod.OPTIONS)
                            .check(r -> {
                                log.info("检查你登录没");
                                StpUtil.checkLogin();
                                log.info("检查你登录没");
                            });
                    // 空间级登录认证
                    SaRouter.match("/space_user/**")
                                    .check(r ->  {
                                        log.info("检查你登录space账户没有");
                                        StpKit.SPACE.checkLogin();
                                        log.info("检查你登录space账户没有");
                                    });

                    SaRouter.match("/admin/**").check(r ->
                            StpUtil.checkRole("admin"));
//                    SaRouter.match("/space_user/**").check(r -> {
//                        StpKit.SPACE.checkRole("viewer");
//                        System.out.println("团队空间角色校验执行了啊");
//                    });
                    // 排除掉的 path 列表，可以写多个
                })

                // 异常处理函数：每次认证函数发生异常时执行此函数
                .setError(e -> {
                    return SaResult.error(e.getMessage());
                })

                // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(obj -> {
                    SaManager.getLog().debug("处理跨域问题");
                    SaHolder.getResponse()
                            // ---------- 设置跨域响应头 ----------
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "*")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "3600")
                    ;
                })
                ;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 注解拦截器，打开注解鉴权功能
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }

//    @PostConstruct
//    public void rewriteSaStrategy() {
//        // 重写Sa-Token的注解处理器，增加注解合并功能
//        SaAnnotationStrategy.instance.getAnnotation = (element, annotationClass) -> {
//            return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
//        };
//    }



}